package frontend;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;
import javax.swing.text.NumberFormatter;

import model.LoansOfPersonTableModel;
import net.miginfocom.swing.MigLayout;
import domain.Customer;
import domain.Library;
import domain.Loan;
import factory.DisposeOnEscapeFactory;

public class CustomerDetailJFrame extends JFrame implements Observer {
    private static final long serialVersionUID = 7061669766358324813L;
    private Customer customer;
    private JPanel contentPane;
    private JTable tblLoans;

    private static HashMap<Customer, CustomerDetailJFrame> instance = new HashMap<Customer, CustomerDetailJFrame>();
    private JLabel lblAnzahlExemplareValue;
    private JPanel pnlLoansOf;
    private JLabel lblNameValue;
    private JLabel lblStreetValue;
    private JLabel lblZipCityValue;
    private JButton btnRckgabe;
    private static Library library = Library.getInstance();
    private JButton btnAusleihen;

    public static CustomerDetailJFrame getInstance(Customer customer) {
        if (!instance.containsKey(customer)) {
            instance.put(customer, new CustomerDetailJFrame(customer));
        }
        return instance.get(customer);
    }

    public static boolean hasInstance(Customer customer) {
        return instance.containsKey(customer);
    }

    @Override
    public void dispose() {
        super.dispose();
        instance.remove(customer);
    }

    /**
     * Create the frame.
     */
    public CustomerDetailJFrame(Customer customer) {
        this.customer = customer;
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        DisposeOnEscapeFactory.appendDisposeOnEscapeToJFrame(this);
        setBounds(100, 100, 450, 388);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[] { 0, 0 };
        gbl_contentPane.rowHeights = new int[] { 0, 0, 0 };
        gbl_contentPane.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
        gbl_contentPane.rowWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
        contentPane.setLayout(gbl_contentPane);

        JPanel pnlCustomerSelection = new JPanel();
        pnlCustomerSelection.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Kunde", TitledBorder.LEADING, TitledBorder.TOP,
                null, null));
        GridBagConstraints gbc_pnlCustomerSelection = new GridBagConstraints();
        gbc_pnlCustomerSelection.fill = GridBagConstraints.HORIZONTAL;
        gbc_pnlCustomerSelection.insets = new Insets(0, 0, 5, 0);
        gbc_pnlCustomerSelection.gridx = 0;
        gbc_pnlCustomerSelection.gridy = 0;
        contentPane.add(pnlCustomerSelection, gbc_pnlCustomerSelection);
        pnlCustomerSelection.setLayout(new MigLayout("", "[100px:100px:100px][50px:50px,grow,leading]", "[][][]"));

        JLabel lblKennung = new JLabel("Name");
        pnlCustomerSelection.add(lblKennung, "cell 0 0,alignx left,aligny baseline");

        NumberFormatter format = new NumberFormatter();
        format.setAllowsInvalid(true);
        format.setMinimum(0);
        format.setValueClass(Integer.class);

        lblNameValue = new JLabel("New label");
        pnlCustomerSelection.add(lblNameValue, "cell 1 0,alignx left,aligny baseline");

        JLabel lblStreet = new JLabel("Strasse");
        pnlCustomerSelection.add(lblStreet, "cell 0 1,alignx left");

        lblStreetValue = new JLabel("New label");
        pnlCustomerSelection.add(lblStreetValue, "cell 1 1,alignx left");

        JLabel lblZipCity = new JLabel("PLZ / Ort");
        pnlCustomerSelection.add(lblZipCity, "cell 0 2");

        lblZipCityValue = new JLabel("New label");
        pnlCustomerSelection.add(lblZipCityValue, "cell 1 2,alignx left");

        pnlLoansOf = new JPanel();
        pnlLoansOf.setBorder(new TitledBorder(null, "Ausleihen von: {0}", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        GridBagConstraints gbc_pnlLoansOf = new GridBagConstraints();
        gbc_pnlLoansOf.fill = GridBagConstraints.BOTH;
        gbc_pnlLoansOf.gridx = 0;
        gbc_pnlLoansOf.gridy = 1;
        contentPane.add(pnlLoansOf, gbc_pnlLoansOf);
        pnlLoansOf.setLayout(new MigLayout("", "[100px:100px:100px,grow][][grow][][]", "[][grow]"));

        JLabel lblNewLabel = new JLabel("Anzahl Exemplare");
        pnlLoansOf.add(lblNewLabel, "cell 0 0,growx");

        lblAnzahlExemplareValue = new JLabel("{0}");
        pnlLoansOf.add(lblAnzahlExemplareValue, "cell 1 0");

        Component horizontalGlue = Box.createHorizontalGlue();
        pnlLoansOf.add(horizontalGlue, "cell 2 0");

        btnRckgabe = new JButton("Rückgabe");
        pnlLoansOf.add(btnRckgabe, "cell 3 0,alignx right");

        btnAusleihen = new JButton("Ausleihen");
        pnlLoansOf.add(btnAusleihen, "cell 4 0,alignx right");

        tblLoans = new JTable();
        tblLoans.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane scrollPane = new JScrollPane(tblLoans);
        scrollPane.setEnabled(false);
        pnlLoansOf.add(scrollPane, "cell 0 1 5 1,grow");

        library.addObserver(this);

        addActionListeners();

        loadCustomerValues();
        setShortcuts();
    }

    private void setShortcuts() {
        btnRckgabe.setMnemonic(KeyEvent.VK_R);
        btnAusleihen.setMnemonic(KeyEvent.VK_A);
    }
    
    private void addActionListeners() {
        btnRckgabe.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                int res = JOptionPane.showConfirmDialog(CustomerDetailJFrame.this, "Möchten Sie die selektierte Ausleihe zurückgeben",
                        "Ausleihe zurückgeben?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (res == JOptionPane.OK_OPTION) {
                    Loan loan = ((LoansOfPersonTableModel) tblLoans.getModel()).getElementAt(tblLoans.getSelectedRow());
                    library.returnLoan(loan);
                }
            }
        });
        btnAusleihen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                CreateLoanJFrame.getInstance(CustomerDetailJFrame.this.customer).setVisible(true);
            }
        });
        
        tblLoans.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent arg0) {
                updateButtonStates();
            }
        });
    }
    
    private void updateButtonStates() {
        btnRckgabe.setEnabled(tblLoans.getSelectedRows().length > 0);
    }

    private void loadCustomerValues() {
        lblNameValue.setText(this.customer.getSurname() + " " + this.customer.getName());
        lblStreetValue.setText(this.customer.getStreet());
        lblZipCityValue.setText(this.customer.getZip() + " " + this.customer.getCity());

        tblLoans.setModel(LoansOfPersonTableModel.getInstance(this.customer));
        tblLoans.setRowSorter(new TableRowSorter<LoansOfPersonTableModel>(LoansOfPersonTableModel.getInstance(this.customer)));
        List<Loan> loans = library.getCustomerOpenLoans(this.customer);
        lblAnzahlExemplareValue.setText("" + loans.size());
        pnlLoansOf.setBorder(new TitledBorder(null, "Ausleihen von: " + this.customer.getSurname() + " " + this.customer.getName(),
                TitledBorder.LEADING, TitledBorder.TOP, null, null));
        tblLoans.getColumnModel().getColumn(0).setMinWidth(40);
        tblLoans.getColumnModel().getColumn(0).setMaxWidth(40);
        tblLoans.getColumnModel().getColumn(1).setMinWidth(120);
        tblLoans.getColumnModel().getColumn(2).setMinWidth(80);
        updateModifiablyValues();
    }

    private void updateModifiablyValues() {
        List<Loan> loans = library.getCustomerOpenLoans(this.customer);
        lblAnzahlExemplareValue.setText("" + loans.size());
        updateButtonStates();
    }

    @Override
    public void update(Observable o, Object arg) {
        updateModifiablyValues();
    }
}
